﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using MySql.Data.MySqlClient;
using Services.Common;
using BartonExtension;
using SQLWrapper;
using Model.App;
using Model.Images;
using Model.Weixin;
using Model;

using Services.PushNotification;

namespace Services.User
{
    public class ISMFriendServiceProvider : ISMServiceProvider
    {
        public const string FRIEND_SET_CRONY_STATE = "friend_set_crony_state";
        public const string DELETE_FRIEND = "delete_friend";
        public const string ADD_FRIEND = "add_friend";
        public const string COMFIRM_FRIEND_REQ = "comfirm_friend_req";
        public const string GET_FRIEND_REQ = "get_friend_req";
        public const string UPDATE_REQ_READ_TAG = "update_req_read_tag";
        public const string CHECK_FRIEND_STATUS = "check_friend_status";
        public override Task<ISMServiceResult> doProcess(ISMServiceModel model)
        {
            if (model.operationIdentifier.Equals(FRIEND_SET_CRONY_STATE))
            {
                ISMFriendCronyRequest request = model.GetState<ISMFriendCronyRequest>();
                return SetCronyState(request);
            }
            else if(model.operationIdentifier.Equals(DELETE_FRIEND))
            {
                ISMDeleteFriendRequest request = model.GetState<ISMDeleteFriendRequest>();
                return DeleteFriend(request);
            }
            else if(model.operationIdentifier.Equals(ADD_FRIEND))
            {
                ISMAddFriendRequest request = model.GetState<ISMAddFriendRequest>();
                return AddFriend(request);
            }
            else if(model.operationIdentifier.Equals(COMFIRM_FRIEND_REQ))
            {
                ISMComfirmFriendRequest request = model.GetState<ISMComfirmFriendRequest>();
                return ComfirmFriend(request);
            }
            else if(model.operationIdentifier.Equals(GET_FRIEND_REQ))
            {
                ISMGetFriendAppliesRequest request = model.GetState<ISMGetFriendAppliesRequest>();
                return GetFriendAppliesRequest(request);
            }
            else if(model.operationIdentifier.Equals(UPDATE_REQ_READ_TAG))
            {
                ISMRecvRecipRequest request = model.GetState<ISMRecvRecipRequest>();
                return UpdateReqestRecvTag(request);
            }
            else if(model.operationIdentifier.Equals(CHECK_FRIEND_STATUS))
            {
                ISMFriendStatusCheckRequest request = model.GetState<ISMFriendStatusCheckRequest>();
                return GetFriendStatus(request);
            }
            return base.defaultProcess();
        }
        private Task<ISMServiceResult> UpdateReqestRecvTag(ISMRecvRecipRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();
                    MySQLOperationManager.doSQLOperation(cmd =>
                        {
                            cmd.CommandText = "proc_client_update_friend_request_receivetag";
                            cmd.Parameters.Add("?_uid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                            cmd.Parameters.Add("?errorcode", MySqlDbType.Int32, ParameterDirection.Output);
                            cmd.ExecuteNonQuery();
                            int errorcode = cmd.Parameters["?errorcode"].Value.toInt32().Value;
                            if (errorcode == -1)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorMsg = e;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                            }
                        },CommandType.StoredProcedure,false);
                    return result;
                });
        }
        private Task<ISMServiceResult> GetFriendAppliesRequest(ISMGetFriendAppliesRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();
                    MySQLOperationManager.doSQLOperationWithLoadedData(cmd =>
                        {
                            cmd.CommandText = "proc_client_get_friend_requests";
                            cmd.Parameters.Add("?_uid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                                result.errorMsg = e;
                            }
                        },
                        data =>
                        {
                            if (data.Count == 1 && data.First().ContainsKey("error"))
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                            else
                            {
                                List<ISMFriendReq> reqs = new List<ISMFriendReq>();
                                data.ForEach(d =>
                                {
                                    ISMFriendReq req = new ISMFriendReq()
                                    {
                                        ID = d["ID"].toUInt64().Value,
                                        content = d["content"].ToString(),
                                        requester = new ISMUserinfo()
                                        {
                                            ID = d["uid"].toInt64().Value,
                                            openId = d["openid"].ToString(),
                                            intopenid = d["intopenid"].toUInt64().Value.ToString(),
                                            wechatName = d["wechatname"].ToString(),
                                            username = d["username"].ToString(),
                                            sex = d["sex"].toEnum<Sex>(),
                                            vocation = d["vocation"].ToString(),
                                            company = d["company"].ToString(),
                                            occupation = d["occupation"].ToString(),
                                            mobile = d["mobile"].ToString(),
                                            telephone = d["telephone"].ToString(),
                                            email = d["email"].ToString(),
                                            officeAddress = d["officeaddress"].ToString(),
                                            piccardUrl = d["piccardUrl"].ToString(),
                                            videocardUrl = d["videocardUrl"].ToString(),
                                            headimgUrl = d["headimgUrl"].ToString()
                                        },
                                        timetag = d["timetag"].ToString()
                                    };
                                    reqs.Add(req);
                                });
                                result.dbReturningState = reqs;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
        private Task<ISMServiceResult> SetCronyState(ISMFriendCronyRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();

                    MySQLOperationManager.doSQLOperation(cmd =>
                        {
                            cmd.CommandText = "proc_client_set_friend_crony";
                            cmd.Parameters.Add("?_uid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_friid", request.friid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_crony", request.cronyFlag, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                            cmd.Parameters.Add("?errorcode", MySqlDbType.Int32, ParameterDirection.Output);
                            cmd.ExecuteNonQuery();
                            int errorcode = cmd.Parameters["?errorcode"].Value.toInt32().Value;
                            if(errorcode == 0)
                            {
                                Cache.CacheManager.instance.RemoveCache(request.uid.ToString());
                            }
                            else if(errorcode == -2)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                            else if(errorcode == -1)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_UNKNOWN_ERR;
                                result.errorMsg = "你们不是好友关系";
                            }
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorMsg = e;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
        private Task<ISMServiceResult> DeleteFriend(ISMDeleteFriendRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();

                    MySQLOperationManager.doSQLOperation(cmd =>
                        {
                            cmd.CommandText = "proc_client_delete_friend";
                            cmd.Parameters.Add("?_ownid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_friid", request.friid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                            cmd.Parameters.Add("?errorcode", MySqlDbType.Int32, ParameterDirection.Output);
                            cmd.ExecuteNonQuery();
                            int errorcode = cmd.Parameters["?errorcode"].Value.toInt32().Value;
                            if(errorcode == -1)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                            else if(errorcode == 0)
                            {
                                
                            }
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                                result.errorMsg = e;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
        private Task<ISMServiceResult> AddFriend(ISMAddFriendRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();
                    MySQLOperationManager.doSQLOperation(cmd =>
                        {
                            cmd.CommandText = "proc_client_add_friend_request";
                            cmd.Parameters.Add("?_requesterid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_to_id", request.friid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_content", request.content, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                            cmd.Parameters.Add("?errorcode", MySqlDbType.Int32, ParameterDirection.Output);
                            cmd.ExecuteNonQuery();
                            int errorcode = cmd.Parameters["?errorcode"].Value.toInt32().Value;
                            if(errorcode == -1)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_FRIEND_TOO_MANY_ADDFRIEND_REQUEST;
                                result.errorMsg = "发送好友请求太频繁";
                            }
                            else if(errorcode == -2)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                            else if (errorcode == -3)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_FRIEND_RELATION_EXISTS;
                                result.errorMsg = "好友关系已存在";
                            }
                            else if (errorcode == 0)
                            {
                                //Clean Cache

                                //Push Notification
                                ISMPushContent content = new ISMPushContent()
                                {
                                    receiverId = request.friid.ToString(),
                                    type = ISMPushType.kPushTypeFriendRequest,
                                    fromId = request.uid.ToString(),
                                    title = "新的朋友",
                                    context = "有人添加您为好友啦，快去看看吧"
                                };
                                Pusher.Push(content);
                            }
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                                result.errorMsg = e;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
        private Task<ISMServiceResult> ComfirmFriend(ISMComfirmFriendRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();
                    MySQLOperationManager.doSQLOperation(cmd =>
                        {
                            cmd.CommandText = "proc_client_comfirm_friend_request";
                            cmd.Parameters.Add("?_friend_request_id", request.friend_request_id, ParameterDirection.Input);
                            cmd.Parameters.Add("?_comfirmed_by", request.confirmed_by, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                            cmd.Parameters.Add("?errorcode", MySqlDbType.Int32, ParameterDirection.Output);
                            cmd.ExecuteNonQuery();
                            int errorcode = cmd.Parameters["?errorcode"].Value.toInt32().Value;
                            if(errorcode == -1)
                            {
                                result.isOperationSuccess = false;
                                result.errorMsg = "好友关系已存在";
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_FRIEND_RELATION_EXISTS;
                            }
                            else if(errorcode == -2)
                            {
                                result.isOperationSuccess = false;
                                result.errorMsg = "Token 验证失败";
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                            }
                            else if(errorcode == 0)
                            {
                                Cache.CacheManager.instance.RemoveCache(request.confirmed_by.ToString());
                            }
                        },
                        e =>
                        {
                            if(e != null)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                                result.errorMsg = e;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
        private Task<ISMServiceResult> GetFriendStatus(ISMFriendStatusCheckRequest request)
        {
            return Task.Factory.StartNew<ISMServiceResult>(() =>
                {
                    ISMServiceResult result = new ISMServiceResult();
                    MySQLOperationManager.doSQLOperationWithLoadedData(cmd =>
                        {
                            cmd.CommandText = "proc_client_friend_status_check";
                            cmd.Parameters.Add("?_uid", request.uid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_checkid", request.checkid, ParameterDirection.Input);
                            cmd.Parameters.Add("?_token", request.token, ParameterDirection.Input);
                        },
                        e =>
                        {
                            if(e!=null)
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_EXCEPTION_ERR;
                                result.errorMsg = e;
                            }
                        },
                        data =>
                        {
                            if(data.Count == 1 && data.First().ContainsKey("error"))
                            {
                                result.isOperationSuccess = false;
                                result.errorCode = ISMServiceResultErrorCodes.ERR_CODE_ISM_TOKEN_ERROR;
                                result.errorMsg = "Token 验证失败";
                            }
                            else
                            {
                                ISMFriendStatus status = new ISMFriendStatus()
                                {
                                    uid = request.checkid,
                                    isFriend = false,
                                    isCrony = false
                                };
                                data.ForEach(d =>
                                    {
                                        status.isFriend = true;
                                        if(request.uid == d["a_id"].toUInt64().Value)
                                        {
                                            status.isCrony = d["btoa_cronyflag"].toBoolean().Value;
                                        }
                                        else if(request.uid == d["b_id"].toUInt64().Value)
                                        {
                                            status.isCrony = d["atob_cronyflag"].toBoolean().Value;
                                        }
                                        return;
                                    });
                                result.dbReturningState = status;
                            }
                        }, CommandType.StoredProcedure, false);
                    return result;
                });
        }
    }
}
